package com.ruoyi.common.utils;

import java.util.HashMap;
import java.util.Map;

/**
 * 港区水务系统水价计算器
 * 基于《郑州市城市集中供水价格表》开发
 */
public class WaterPriceCalculator {

    // 用水性质枚举
    public enum WaterUsageType {
        RESIDENTIAL_TIERED,     // 居民生活用水（阶梯式）
        RESIDENTIAL_NON_TIERED, // 居民生活用水（非阶梯式）
        NON_RESIDENTIAL,        // 非居民生活用水
        SPECIAL                 // 特种用水
    }

    // 水价配置类
    private static class WaterPriceConfig {
        double basePrice;      // 基本水价
        double sewageFee;      // 污水处理费
        double taxFreeWater;   // 不征税自采水
        double totalPrice;     // 综合水价

        public WaterPriceConfig(double basePrice, double sewageFee, double taxFreeWater, double totalPrice) {
            this.basePrice = basePrice;
            this.sewageFee = sewageFee;
            this.taxFreeWater = taxFreeWater;
            this.totalPrice = totalPrice;
        }
    }

    // 阶梯水价配置
    private static class TieredPriceConfig {
        int tier1Limit = 180;   // 第一阶梯上限
        int tier2Limit = 300;   // 第二阶梯上限
        double tier1Price;      // 第一阶梯价格
        double tier2Price;      // 第二阶梯价格
        double tier3Price;      // 第三阶梯价格

        public TieredPriceConfig(double tier1Price, double tier2Price, double tier3Price) {
            this.tier1Price = tier1Price;
            this.tier2Price = tier2Price;
            this.tier3Price = tier3Price;
        }
    }

    // 水价配置映射
    private static final Map<WaterUsageType, Object> PRICE_CONFIG = new HashMap<>();

    static {
        // 初始化水价配置
        PRICE_CONFIG.put(WaterUsageType.RESIDENTIAL_TIERED,
                new TieredPriceConfig(4.40, 5.95, 10.60));

        PRICE_CONFIG.put(WaterUsageType.RESIDENTIAL_NON_TIERED,
                new WaterPriceConfig(3.20, 0.95, 0.35, 4.50));

        PRICE_CONFIG.put(WaterUsageType.NON_RESIDENTIAL,
                new WaterPriceConfig(4.15, 1.40, 0.40, 5.95));

        PRICE_CONFIG.put(WaterUsageType.SPECIAL,
                new WaterPriceConfig(14.75, 1.40, 2.00, 18.15));
    }

    /**
     * 获取用水价格
     * @param priceCode 用水价格编码
     * @return 用水价格枚举
     */
    public static WaterUsageType getWaterPrice(String priceCode) {

        switch (priceCode) {
            case "202509221157":
                return WaterUsageType.RESIDENTIAL_TIERED;
            case "202509221756":
                return WaterUsageType.RESIDENTIAL_NON_TIERED;
            case "202509221758":
                return WaterUsageType.NON_RESIDENTIAL;
            case "202509221760":
                return WaterUsageType.SPECIAL;
            default:
                throw new IllegalArgumentException("不支持的用水价格");
        }
    }

    /**
     * 计算水费
     * @param usageType 用水性质
     * @param waterUsage 用水量（立方米）
     * @return 总水费（元）
     */
    public static double calculateWaterFee(WaterUsageType usageType, double waterUsage) {
        if (waterUsage < 0) {
            throw new IllegalArgumentException("用水量不能为负数");
        }

        switch (usageType) {
            case RESIDENTIAL_TIERED:
                return calculateTieredWaterFee(waterUsage);
            case RESIDENTIAL_NON_TIERED:
            case NON_RESIDENTIAL:
            case SPECIAL:
                WaterPriceConfig config = (WaterPriceConfig) PRICE_CONFIG.get(usageType);
                return waterUsage * config.totalPrice;
            default:
                throw new IllegalArgumentException("不支持的用水性质");
        }
    }

    /**
     * 计算阶梯水费（居民生活用水阶梯式）
     * @param waterUsage 用水量（立方米）
     * @return 总水费（元）
     */
    private static double calculateTieredWaterFee(double waterUsage) {
        TieredPriceConfig tieredConfig = (TieredPriceConfig) PRICE_CONFIG.get(WaterUsageType.RESIDENTIAL_TIERED);

        double totalFee = 0.0;

        if (waterUsage <= tieredConfig.tier1Limit) {
            // 第一阶梯
            totalFee = waterUsage * tieredConfig.tier1Price;
        } else if (waterUsage <= tieredConfig.tier2Limit) {
            // 第二阶梯
            totalFee = tieredConfig.tier1Limit * tieredConfig.tier1Price +
                    (waterUsage - tieredConfig.tier1Limit) * tieredConfig.tier2Price;
        } else {
            // 第三阶梯
            totalFee = tieredConfig.tier1Limit * tieredConfig.tier1Price +
                    (tieredConfig.tier2Limit - tieredConfig.tier1Limit) * tieredConfig.tier2Price +
                    (waterUsage - tieredConfig.tier2Limit) * tieredConfig.tier3Price;
        }

        return totalFee;
    }

    /**
     * 获取详细水费明细
     * @param usageType 用水性质
     * @param waterUsage 用水量（立方米）
     * @return 水费明细对象
     */
    public static WaterFeeDetail getWaterFeeDetail(WaterUsageType usageType, double waterUsage) {
        if (waterUsage < 0) {
            throw new IllegalArgumentException("用水量不能为负数");
        }

        WaterFeeDetail detail = new WaterFeeDetail();
        detail.setUsageType(usageType);
        detail.setWaterUsage(waterUsage);

        if (usageType == WaterUsageType.RESIDENTIAL_TIERED) {
            // 阶梯水价明细计算
            TieredPriceConfig tieredConfig = (TieredPriceConfig) PRICE_CONFIG.get(usageType);

            if (waterUsage <= tieredConfig.tier1Limit) {
                detail.setTier1Usage(waterUsage);
                detail.setTier1Fee(waterUsage * tieredConfig.tier1Price);
            } else if (waterUsage <= tieredConfig.tier2Limit) {
                detail.setTier1Usage(tieredConfig.tier1Limit);
                detail.setTier2Usage(waterUsage - tieredConfig.tier1Limit);
                detail.setTier1Fee(tieredConfig.tier1Limit * tieredConfig.tier1Price);
                detail.setTier2Fee(detail.getTier2Usage() * tieredConfig.tier2Price);
            } else {
                detail.setTier1Usage(tieredConfig.tier1Limit);
                detail.setTier2Usage(tieredConfig.tier2Limit - tieredConfig.tier1Limit);
                detail.setTier3Usage(waterUsage - tieredConfig.tier2Limit);
                detail.setTier1Fee(tieredConfig.tier1Limit * tieredConfig.tier1Price);
                detail.setTier2Fee(detail.getTier2Usage() * tieredConfig.tier2Price);
                detail.setTier3Fee(detail.getTier3Usage() * tieredConfig.tier3Price);
            }
            detail.setTotalFee(detail.getTier1Fee() + detail.getTier2Fee() + detail.getTier3Fee());

        } else {
            // 非阶梯水价明细
            WaterPriceConfig config = (WaterPriceConfig) PRICE_CONFIG.get(usageType);
            detail.setBaseWaterFee(waterUsage * config.basePrice);
            detail.setSewageFee(waterUsage * config.sewageFee);
            detail.setTaxFreeWaterFee(waterUsage * config.taxFreeWater);
            detail.setTotalFee(waterUsage * config.totalPrice);
        }

        return detail;
    }

    /**
     * 水费明细类
     */
    public static class WaterFeeDetail {
        private WaterUsageType usageType;
        private double waterUsage;
        private double totalFee;

        // 阶梯用水量
        private double tier1Usage;
        private double tier2Usage;
        private double tier3Usage;

        // 阶梯费用
        private double tier1Fee;
        private double tier2Fee;
        private double tier3Fee;

        // 费用明细（非阶梯）
        private double baseWaterFee;
        private double sewageFee;
        private double taxFreeWaterFee;

        // getter和setter方法
        public WaterUsageType getUsageType() { return usageType; }
        public void setUsageType(WaterUsageType usageType) { this.usageType = usageType; }

        public double getWaterUsage() { return waterUsage; }
        public void setWaterUsage(double waterUsage) { this.waterUsage = waterUsage; }

        public double getTotalFee() { return totalFee; }
        public void setTotalFee(double totalFee) { this.totalFee = totalFee; }

        public double getTier1Usage() { return tier1Usage; }
        public void setTier1Usage(double tier1Usage) { this.tier1Usage = tier1Usage; }

        public double getTier2Usage() { return tier2Usage; }
        public void setTier2Usage(double tier2Usage) { this.tier2Usage = tier2Usage; }

        public double getTier3Usage() { return tier3Usage; }
        public void setTier3Usage(double tier3Usage) { this.tier3Usage = tier3Usage; }

        public double getTier1Fee() { return tier1Fee; }
        public void setTier1Fee(double tier1Fee) { this.tier1Fee = tier1Fee; }

        public double getTier2Fee() { return tier2Fee; }
        public void setTier2Fee(double tier2Fee) { this.tier2Fee = tier2Fee; }

        public double getTier3Fee() { return tier3Fee; }
        public void setTier3Fee(double tier3Fee) { this.tier3Fee = tier3Fee; }

        public double getBaseWaterFee() { return baseWaterFee; }
        public void setBaseWaterFee(double baseWaterFee) { this.baseWaterFee = baseWaterFee; }

        public double getSewageFee() { return sewageFee; }
        public void setSewageFee(double sewageFee) { this.sewageFee = sewageFee; }

        public double getTaxFreeWaterFee() { return taxFreeWaterFee; }
        public void setTaxFreeWaterFee(double taxFreeWaterFee) { this.taxFreeWaterFee = taxFreeWaterFee; }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("用水性质: ").append(usageType).append("\n");
            sb.append("用水量: ").append(String.format("%.2f", waterUsage)).append(" 立方米\n");
            sb.append("总水费: ").append(String.format("%.2f", totalFee)).append(" 元\n");

            if (usageType == WaterUsageType.RESIDENTIAL_TIERED) {
                sb.append("阶梯水费明细:\n");
                if (tier1Usage > 0) {
                    sb.append("  第一阶梯: ").append(String.format("%.2f", tier1Usage))
                            .append("m³ × 4.40元 = ").append(String.format("%.2f", tier1Fee)).append("元\n");
                }
                if (tier2Usage > 0) {
                    sb.append("  第二阶梯: ").append(String.format("%.2f", tier2Usage))
                            .append("m³ × 5.95元 = ").append(String.format("%.2f", tier2Fee)).append("元\n");
                }
                if (tier3Usage > 0) {
                    sb.append("  第三阶梯: ").append(String.format("%.2f", tier3Usage))
                            .append("m³ × 10.60元 = ").append(String.format("%.2f", tier3Fee)).append("元\n");
                }
            } else {
                WaterPriceConfig config = (WaterPriceConfig) PRICE_CONFIG.get(usageType);
                sb.append("费用明细:\n");
                sb.append("  基本水费: ").append(String.format("%.2f", waterUsage))
                        .append("m³ × ").append(config.basePrice).append("元 = ")
                        .append(String.format("%.2f", baseWaterFee)).append("元\n");
                sb.append("  污水处理费: ").append(String.format("%.2f", waterUsage))
                        .append("m³ × ").append(config.sewageFee).append("元 = ")
                        .append(String.format("%.2f", sewageFee)).append("元\n");
                sb.append("  不征税水费: ").append(String.format("%.2f", waterUsage))
                        .append("m³ × ").append(config.taxFreeWater).append("元 = ")
                        .append(String.format("%.2f", taxFreeWaterFee)).append("元\n");
            }

            return sb.toString();
        }
    }

    /**
     * 测试示例
     */
    public static void main(String[] args) {
        // 测试用例
        System.out.println("=== 郑州市水务系统水价计算测试 ===\n");

        // 居民阶梯用水测试
        testResidentialTiered(150);  // 第一阶梯
        testResidentialTiered(250);  // 第二阶梯
        testResidentialTiered(350);  // 第三阶梯

        // 其他用水类型测试
        testWaterFee(WaterUsageType.RESIDENTIAL_NON_TIERED, 200, "居民非阶梯用水");
        testWaterFee(WaterUsageType.NON_RESIDENTIAL, 100, "非居民用水");
        testWaterFee(WaterUsageType.SPECIAL, 50, "特种用水");
    }

    private static void testResidentialTiered(double usage) {
        System.out.println("居民阶梯用水 " + usage + " 立方米:");
        WaterFeeDetail detail = getWaterFeeDetail(WaterUsageType.RESIDENTIAL_TIERED, usage);
        System.out.println(detail);
        System.out.println("----------------------------------------");
    }

    private static void testWaterFee(WaterUsageType type, double usage, String description) {
        System.out.println(description + " " + usage + " 立方米:");
        WaterFeeDetail detail = getWaterFeeDetail(type, usage);
        System.out.println(detail);
        System.out.println("----------------------------------------");
    }
}
